package com.example.net

import android.os.Environment
import com.alibaba.android.arouter.launcher.ARouter
import com.example.base.app.conts.BaseConst
import com.example.base.app.path.RouterPath
import com.tencent.mmkv.MMKV
import okhttp3.Cache
import okhttp3.Interceptor
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Protocol
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import org.json.JSONObject
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.net.Proxy
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLHandshakeException
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager

object HttpManager {
    //获取一个OKHttpClient
    private fun getOkHttpClient(): OkHttpClient {
        val build = OkHttpClient.Builder()//建造者设计模式
            .apply {
                //写超时
                writeTimeout(5000, TimeUnit.SECONDS)
                //读超时
                readTimeout(5000,TimeUnit.SECONDS)
                //写超时
                connectTimeout(5000,TimeUnit.SECONDS)
                //设置日志拦截器(避免线上环境给系统输出日志)
                if (BuildConfig.isOpenLog){//构建中生成的
                    addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                }
                //Header头拦截器
                addInterceptor(getHeaderInterceptor())
                //服务器异常拦截器
                addInterceptor(getServiceInterceptor())
                //如果要支持Https请求，支持加密传输（对称和非对称都可以）
                sslSocketFactory(sslSocketFactory, trustManager)
                //防止他人使用网络代理抓包
                proxy(Proxy.NO_PROXY)
                //设置Http网络协议版本，Http1.0 Http2.0和http3.0/QUIC
                protocols(listOf(Protocol.HTTP_2,Protocol.HTTP_1_1))
                //网络缓存(默认情况下是没有网络缓存的)(10*1024*1024 = 10兆)
                //外部存储目录
                val externalDirPath = Environment.getExternalStorageDirectory().absolutePath
                if (externalDirPath.isNotEmpty()){
                    cache(Cache(File("${externalDirPath}/smartParkCache"),10*1024*1024))
                }

            }
        return build.build()
    }
    //
    private val sslSocketFactory: SSLSocketFactory
        get() = try {
            val sslContent = SSLContext.getInstance("SSL")
            sslContent.init(null, arrayOf(), SecureRandom())
            sslContent.socketFactory
        }catch (e:Exception){
            throw e
        }
    private val trustManager: X509TrustManager
        get() = object :X509TrustManager{
            //校验客户端的证书
            override fun checkClientTrusted(p0: Array<out X509Certificate>?, p1: String?) {

            }
            //校验服务端证书(一般校验服务端)可以进行判断
            override fun checkServerTrusted(p0: Array<out X509Certificate>?, p1: String?) {
                //防止抓包 Fiddler，Charles抓包工具
                p0?.forEach {
                    if (it.issuerX500Principal.name.contains("Charles") ||
                        it.issuerX500Principal.name.contains("Fiddler")){
                        throw SSLHandshakeException("当前应用不允许代理抓包，请放弃抓包行为")

                    }
                }
            }
            //获取可以被接收的端
            override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
        }
    /**
     * 请求头拦截器
     * 设计模式 任务链模式
     */
    private fun getHeaderInterceptor(): Interceptor {
        return object :Interceptor{
            override fun intercept(chain: Interceptor.Chain): Response {
                val token = MMKV.defaultMMKV().getString("token",BaseConst.APP_TOKEN).toString()
                //获取AccessID
                val accessId = MMKV.defaultMMKV().decodeString("accessId", BaseConst.APP_ACCESS_ID).toString()

                //从请求链上获取请求对象
                val proceed = chain.proceed(chain.request().newBuilder().addHeader("token",token)
                    .addHeader("accessId",accessId)
                    .build())
                //校验token 是否过期
                if (proceed.code == 403 || proceed.code == 401){
                    ARouter.getInstance().build(RouterPath.PATH_LOGIN_PAGE).navigation()
                }
                return proceed
            }
        }
    }
    /**
     * 服务器返回拦截器
     *
     */
    private fun getServiceInterceptor():Interceptor{
        return object :Interceptor{
            override fun intercept(chain: Interceptor.Chain): Response {
                var build = chain.proceed(chain.request())
                var newBuilder = build.newBuilder()
                //5开头服务器端异常
                if (build.code == 500){
                    val errorJson = JSONObject().apply {
                        put("code",500)
                        put("message","服务器异常，请联系客服")
                    }
                    newBuilder.body(errorJson.toString().toResponseBody("application/json;charset=UTF-8".toMediaTypeOrNull()))
                }
                return newBuilder.build()
            }
        }
    }
    //获取Retrofit对象
    fun getRetrofit(): Retrofit {
        val builder = Retrofit.Builder()
        builder.apply {
            baseUrl(BuildConfig.BASE_URL)
            client(getOkHttpClient())
            addConverterFactory(GsonConverterFactory.create())
        }
        return builder.build()

    }
    fun <T> getApiService(clazz:Class<*>):T{
        return getRetrofit().create(clazz) as T
    }
}